﻿global using SpriteInfo = voidbox.PackedTextureElement;

using voidbox;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using TTEngine.Graphics;
using TTEngine.TTMath;
using static System.Net.Mime.MediaTypeNames;

namespace voidbox.Code
{
    public class VBEngine : IVoidBox
    {
        public VBEngine()
        {
            System = new SystemImpl();
            Debug = new DebugImpl();
            App = new AppImpl();
            Graphics = new GraphicsImpl();
        }
        public ISystem System
        {
            get;
            private set;
        }

        public IDebug Debug
        {
            get;
            private set;
        }

        public IApp App
        {
            get;
            private set;
        }

        public IGraphics Graphics
        {
            get;
            private set;
        }
        public class SystemImpl : ISystem
        {
            public string VersionString => Root.Version;
            public void RunApp(string apppath)
            {
                Root.RunApp(apppath);
            }
            public byte[] LoadBinaryInApp(string apppath, string filepath)
            {
                using var tapp = new VBApp(apppath);
                return tapp.LoadBinary(filepath);
            }
            public string LoadTextInApp(string apppath, string filepath)
            {
                using var tapp = new VBApp(apppath);
                return tapp.LoadText(filepath);
            }
        }
        public class DebugImpl : IDebug
        {
            public void Log(string type, string text)
            {
                Console.WriteLine($"[{type}] {text}");
                global::System.Diagnostics.Debug.WriteLine($"[{type}] {text}");
                Debuger.AddLog($"[{type}] {text}");
            }
            public void Assert(bool condition, string message)
            {
                global::System.Diagnostics.Debug.Assert(condition, message);
            }
            public bool ShowDebugTool { get; set; } = false;
        }
        public class AppImpl : IApp
        {
            public void Exit()
            {
                var stack = Root.AppStack.Pop();
                stack.Dispose();
                if (Root.AppStack.Count > 0)
                {
                    Root.AppStack.Peek().Resume();
                }
                else
                {
                    //退出
                    Environment.Exit(0);
                }
            }
            public ushort PixelWidth => (ushort)Root.AppStack.Peek().Config.PixelWidth;

            public ushort PixelHeight => (ushort)Root.AppStack.Peek().Config.PixelHeight;

            public string GetRootPath()
            {
                return Root.AppStack.Peek().Path;
            }

            public byte[] LoadBinary(string file)
            {
                return Root.AppStack.Peek().LoadBinary(file);
            }

            public string LoadText(string file)
            {
                return Root.AppStack.Peek().LoadText(file);
            }
        }
        class FontImpl : IFontObj
        {
            public ISystemTtfFontFamily family;

            public SpriteInfo GetSprite(int charcode, int fontsize)
            {
                {
                    var spdata = this.family.GetFont(fontsize).GetCharImage((char)charcode, 1);
                    var packelem = Root.AppStack.Peek().gfx_resource.PackedTextureGroup.AddSpriteInfo(spdata, SpriteEffect.GrayAsAlpha, Border.Zero);
                    return packelem;
                }
            }
        }
        public class GraphicsImpl : IGraphics
        {
            public void Clear(Color color)
            {
                TTEngine.API.view.Clear(color);
            }
            public  void DrawSprite(PackedTextureElement sprite, Color32 color,Vector3 pos, Vector2 scale, float rotate)
            {
                var elem = new PackedTextureElementInst();
                elem.ElemID = sprite.index;
                elem.color = color;
                elem.pos= pos;
                elem.scale = scale;
                elem.rotate = rotate;
                var batcher = Root.AppStack.Peek().gfx_batcher.GetPackedTextureInstanceBatcher();
                batcher.AddElementInst(elem);
            }
            public  IFontObj GetFont(byte[] data)
            {

                var font = TTEngine.API.loader.LoadTTF(data);
                return new FontImpl()
                {
                    family = font
                };
            }
            public  SpriteInfo GetLogoSprite()
            {
                return Root.AppStack.Peek().gfx_resource.BlockLogo;
            }
            public void EndDraw()
            {
                Root.AppStack.Peek().gfx_batcher.EndDraw();
            }
        }
    }
}
